/** 模块说明
 *本模块以单纯的库的形式存在，不涉及通信接口，通信功能由调用者控制，
 *本模块负责对接收到的Modbus数据包解包，根据解包后的指令读写寄存器，
 * 然后把结果组包返回给调用者。
 **/

#ifndef _MODBUS_H_
#define _MODBUS_H_

#include <stdint.h>

typedef signed char int8;  /* int8_t和char类型会被一些编译器认为不等同，导致抛出warrning */
typedef uint8_t     uint8;
typedef int32_t     int32;
typedef uint32_t    uint32;
typedef int16_t     int16;
typedef uint16_t    uint16;

/* 系统最多支持的寄存器数 */
#define MODBUS_REGISTER_NUM_MAX 512
/* Modbus读写包中最多包含的寄存器数目(Modbus信息帧允许的最大长度为256个字节)*/
#define MODBUS_REGISTER_REQUEST_NUM_MAX 124

typedef enum
{
    MODBUS_READ_ONLY = 1,  /* 01 --> 只读 */
    MODBUS_WRITE_ONLY,     /* 02 --> 只写*/
    MODBUS_READ_WRITE,     /* 03 --> 读写*/          
} MODBUS_RW_E;

/* 寄存器 */
typedef struct
{
    uint8  rw;        /* 寄存器读写权限 */
    uint16 value;     /* 寄存器值 */
} MODBUS_REGISTER_T;

#define MODBUS_RTU 1  /* 协议RTU格式 */
#define MODBUS_TCP 2  /* 协议TCP格式 */

/* 协议 */
typedef struct
{
    uint8 protocol;     /* MODBUS_RTU or MODBUS_TCP */
    uint8 unitAddress;  /* rtu - 从机地址； tcp - 从机站号 */
} MODBUS_PROTOCOL_DEF_T;

typedef enum
{
    MODBUS_INVALID_BUFFER = -1, /* -1 --> 数据缓存不可用 */
    MODBUS_INVALID_FUNC   = 1,  /* 01 --> 非法功能码 */
    MODBUS_INVALID_REGISTER,    /* 02 --> 非法数据地址（从设备中不存在）*/
    MODBUS_INVALID_VALUE,       /* 03 --> 非法数据值（超过范围或者不允许使用）*/
    MODBUS_UNKNOWN_ERROR        /* 04-->从设备出现未知错误 */          
} MODBUS_ERRORCODE_E;

typedef enum
{
    MODBUS_FUNCNO_MIN       = 0x03, /* reserved */
    MODBUS_READ             = 0x03, /* 单读、多读指令 */
    MODBUS_WRITE_ONE        = 0x06, /* 单写 */
    MODBUS_WRITE_MULTI      = 0x10, /* 多写 */
    MODBUS_FUNCNO_MAX       = 0x010 /* reserved */
} MODBUS_FUNCNO_E;

/* ModbusInit() - 初始化，指定协议和通讯收发接口函数
 * 输入 ：protocol - 协议
 *        unitAddress - rtu中为从机地址； tcp中为从机站号
 * 输出 ：0 - 成功; -1 - 失败
 */
int8 ModbusInit(uint8 protocol, uint8 unitAddress);


/* ModbusAddRegisterGroup() - 批量注册寄存器
 * 输入 addressFrom - 起始 (0 based)
 *        addressTo - 结束地址
 *         rw       - 访问权限(全组统一，如单设需调用ModbusAddRegister())
 *        initValue - 寄存器初始化值
 * 输出 ：0 - 成功; -1 - 失败
 */
int8 ModbusAddRegisterGroup(uint16 addressFrom, uint16 addressTo, uint8 rw, uint16 initValue);

/* ModbusAddRegister() - 注册单个寄存器
 * 输入:address - 地址值 (0 based)
 *      rw - 访问权限
 *      initValue - 寄存器初始化值
 * 输出:0 - 成功; -1 - 失败
 */
int8 ModbusAddRegister(uint16 address, uint8 rw, uint16 initValue);


/* ModbusReadRegister() - 读取寄存器值
 * 输入： address - 地址值
 * 输出： > 0XFFFF 失败；其他值 - 后16位为寄存器值  
 * 备注：返回值为int32，当成功返回后，调用者需用uint16转换
 */
uint32 ModbusReadRegister(uint16 address);

/* ModbusWriteRegister() - 写寄存器值
 * 输入:  address - 地址
 *        value - 值
 * 输出：-1 失败；0 - 成功  
 */
int8 ModbusWriteRegister(uint16 address, uint16 value);


/* ModbusHandleRequest() - 处理接收到的Modbus数据包，根据当前的协议类型，
 *                    解包，读取/设置，组包，其中接收缓存与发送缓存共用
 * 输入： buffer - 数据包缓存起始地址
 *       
 * 输出： buffer - 同时作为输出缓存的起始地址
 *       outLen  - 返回的有效数据长度 
 * 返回：0 - 成功； errorCode - 错误码  
 *       
 * 备注：
 *      包括以下错误检查，
 *          1.寄存器地址合法性；2.数据包CRC校验；3.读写权限；
 *          4.数据包功能码合法性；5.设置的值的合法性；6.从设备号正确性
 *
 *      错误码列表：
 *          01 --> 非法功能码，02 --> 非法数据地址（从设备中不存在） 
 *          03 --> 非法数据值（超过范围或者不允许使用） 04-->从设备出现未知错误 
 */
int8 ModBusHandleRequest(uint8 *buffer, uint16 *outLen);

/* PrintBuffer() - 打印协议数据包缓存内容
 * 输入 ：none
 *        
 * 输出 ：none
 */
void PrintBuffer(uint8 *buffer, int32 len);

/* ModbusPrintRegisterList() -打印寄存器列表
 * 输入 ：none
 *        
 * 输出 ：none
 */
void ModbusPrintRegisterList();
#endif /* _MODBUS_H_ */